#include "Util.h"
#include <memory>
#include <sstream>

namespace mylog
{
    namespace Util 
    {
        time_t Date::Now() 
        {
            return time(nullptr);
        }

        bool File::Exists(const std::string& filename)
        {
            struct stat st;
            // stat()函数，返回值为0说明文件信息获取成功，放在了st结构体中；失败返回-1
            return (0 == stat(filename.c_str(), &st));
        }

        std::string File::Path(const std::string& filename)
        {
            if (filename.empty())
                return "";
            // find_last_of()参数列表中接收一个字符集合
            // 从后往前找到第一个出现在该字符集合的字符下标
            int pos = filename.find_last_of("/\\");
            if (pos != std::string::npos)
                return filename.substr(0, pos + 1);
            // 若pos == std::string::npos表示找不到这样的字符，路径无效
            return "";
        }

        void File::CreateDirectory(const std::string& path)
        {
            if (path.empty())
                perror("文件路径为空: ");
            if (!Exists(path))
            {
                size_t pos, index = 0;
                size_t size = path.size();
                while (index < size)
                {
                    pos = path.find_first_of("/\\", index);
                    if (pos == std::string::npos)
                    {
                        mkdir(path.c_str(), 0755);
                        return;
                    }
                    if (pos == index)
                    {
                        index = pos + 1;
                        continue;
                    }
                    std::string sub_path = path.substr(0, pos);
                    if (sub_path == "." || sub_path == "..")
                    {
                        index = pos + 1;
                        continue;
                    }
                    if (Exists(sub_path))
                    {
                        index = pos + 1;
                        continue;
                    }
                    mkdir(sub_path.c_str(), 0755);
                    index = pos + 1;
                }
            }
        }

        int64_t File::FileSize(const std::string& filename)        
        {
            struct stat s;
            auto ret = stat(filename.c_str(), &s);
            if (ret == -1)
            {
                std::cerr << "Get file size failed\n";
                return -1;
            }
            return s.st_size;
        }

        bool File::GetContent(std::string& content, const std::string& filename)
        {
            std::ifstream ifs;
            ifs.open(filename.c_str(), std::ios::binary);
            if (!ifs.is_open()) 
            {
                std::cerr << "file open failed\n";
                return false;
            }
            ifs.seekg(0, std::ios::beg); // 更改文件指针的偏移量
            size_t len = FileSize(filename);
            content.resize(len);
            ifs.read(&content[0], len);
            if (!ifs.good())
            {
                std::cerr << __FILE__ << ":" << __LINE__ << "-" << " read file content failed\n";
                ifs.close();
                return false;
            }
            ifs.close();
            return true;
        }

        bool JsonUtil::Serialize(const Json::Value& val, std::string& str)
        {
            Json::StreamWriterBuilder swb;
            std::unique_ptr<Json::StreamWriter> usw(swb.newStreamWriter());
            std::stringstream ss;
            if (usw->write(val, &ss)) 
            {
                std::cerr << "json serialize failed\n";
                return false;
            }
            str = ss.str();
            return true;
        }

        bool JsonUtil::UnSerialize(const std::string& str, Json::Value& val)
        {
            Json::CharReaderBuilder crb;
            std::unique_ptr<Json::CharReader> ucr(crb.newCharReader());
            std::string err;
            if (ucr->parse(str.c_str(), str.c_str() + str.size(), &val, &err) == false)
            {
                std::cerr << __FILE__ << ":" << __LINE__ << "-" << " json parse error\n";
                return false;
            }
            return true;
        }

        JsonData* JsonData::GetJsonData() 
        {
            static JsonData* json_data = new JsonData;
            return json_data;
        }

        JsonData::JsonData()
        {
            std::string content;
            if (mylog::Util::File::GetContent(content, "./async_log_system.conf") == false)
            {
                std::cerr << __FILE__ << ":" << __LINE__ << "-" << " open async_log_system.conf failed\n";
                perror(NULL);
            }
            Json::Value root;
            mylog::Util::JsonUtil::UnSerialize(content, root);
            buffer_size = root["buffer_size"].asInt64();
            threshold = root["threshold"].asInt64();
            linear_growth = root["linear_growth"].asInt64();
            flush_log = root["flush_log"].asInt64();
            backup_addr = root["backup_addr"].asString();
            backup_port = root["backup_port"].asInt();
            thread_count = root["thread_count"].asInt();
        }

    } // namespace Util

} // namespace log